<template>
  <div class="upload-demo">
    <h2>断点续传模拟演示</h2>
    
    <div class="controls">
      <input type="file" @change="handleFileSelect" />
      <button @click="startUpload" :disabled="uploading">开始上传</button>
      <button @click="simulateNetworkError" :disabled="!uploading">模拟网络错误</button>
      <button @click="simulateBrowserClose" :disabled="!uploading">模拟浏览器关闭</button>
      <button @click="pauseUpload" :disabled="!uploading || paused">暂停上传</button>
      <button @click="resumeUpload" :disabled="!paused">恢复上传</button>
    </div>

    <div class="progress-section">
      <h3>上传进度</h3>
      <div class="progress-bar">
        <div class="progress-fill" :style="{ width: `${progress}%` }"></div>
      </div>
      <div class="progress-text">{{ progress.toFixed(1) }}%</div>
      
      <div class="chunk-status">
        <div v-for="chunk in chunkStatus" :key="chunk.index" 
             class="chunk" :class="chunk.status">
          分片{{ chunk.index + 1 }}
        </div>
      </div>
    </div>

    <div class="logs">
      <h3>操作日志</h3>
      <div v-for="(log, index) in logs" :key="index" class="log-item">
        [{{ log.time }}] {{ log.message }}
      </div>
    </div>
  </div>
</template>

<script>
import { ref, onMounted } from 'vue'

export default {
  name: 'UploadDemo',
  setup() {
    const file = ref(null)
    const uploading = ref(false)
    const paused = ref(false)
    const progress = ref(0)
    const chunkStatus = ref([])
    const logs = ref([])
    let currentUpload = null

    const addLog = (message) => {
      logs.value.unshift({
        time: new Date().toLocaleTimeString(),
        message
      })
      if (logs.value.length > 20) logs.value.pop()
    }

    const handleFileSelect = (event) => {
      file.value = event.target.files[0]
      if (file.value) {
        addLog(`选择了文件: ${file.value.name} (${formatFileSize(file.value.size)})`)
        initializeChunkStatus()
      }
    }

    const initializeChunkStatus = () => {
      if (!file.value) return
      
      const chunkSize = 2 * 1024 * 1024 // 2MB 分片，便于测试
      const totalChunks = Math.ceil(file.value.size / chunkSize)
      chunkStatus.value = Array.from({ length: totalChunks }, (_, index) => ({
        index,
        status: 'pending' // pending, uploading, completed, error
      }))
    }

    const startUpload = async () => {
      if (!file.value) {
        addLog('请先选择文件')
        return
      }

      uploading.value = true
      paused.value = false
      progress.value = 0
      addLog('开始上传...')

      // 模拟上传过程
      currentUpload = simulateUpload()
    }

    const simulateUpload = async () => {
      const totalChunks = chunkStatus.value.length
      let uploadedChunks = 0

      for (let i = 0; i < totalChunks; i++) {
        // 检查是否暂停
        while (paused.value) {
          await new Promise(resolve => setTimeout(resolve, 100))
        }

        // 检查是否取消
        if (!uploading.value) break

        // 更新分片状态
        chunkStatus.value[i].status = 'uploading'
        addLog(`上传分片 ${i + 1}/${totalChunks}`)

        // 模拟上传时间 (1-3秒随机)
        const uploadTime = 1000 + Math.random() * 2000
        
        try {
          // 模拟10%的失败率
          if (Math.random() < 0.1) {
            throw new Error('网络错误')
          }

          await new Promise((resolve, reject) => {
            const timer = setTimeout(() => {
              chunkStatus.value[i].status = 'completed'
              uploadedChunks++
              progress.value = (uploadedChunks / totalChunks) * 100
              addLog(`分片 ${i + 1} 上传完成`)
              resolve()
            }, uploadTime)

            // 保存timer以便取消
            if (currentUpload) currentUpload.timer = timer
          })

        } catch (error) {
          chunkStatus.value[i].status = 'error'
          addLog(`分片 ${i + 1} 上传失败: ${error.message}`)
          uploading.value = false
          break
        }
      }

      if (uploadedChunks === totalChunks) {
        addLog('🎉 文件上传完成！')
        uploading.value = false
      }
    }

    const simulateNetworkError = () => {
      addLog('🔄 模拟网络错误...')
      uploading.value = false
    }

    const simulateBrowserClose = () => {
      addLog('🔄 模拟浏览器关闭...')
      uploading.value = false
      // 实际场景中，这里会保存进度到localStorage
      saveProgressToStorage()
    }

    const pauseUpload = () => {
      paused.value = true
      addLog('⏸️ 上传已暂停')
    }

    const resumeUpload = () => {
      paused.value = false
      addLog('▶️ 恢复上传')
    }

    const saveProgressToStorage = () => {
      if (!file.value) return
      
      const progressData = {
        fileName: file.value.name,
        fileSize: file.value.size,
        uploadedChunks: chunkStatus.value
          .filter(chunk => chunk.status === 'completed')
          .map(chunk => chunk.index),
        timestamp: Date.now()
      }
      
      localStorage.setItem('uploadProgress', JSON.stringify(progressData))
      addLog('进度已保存到本地存储')
    }

    const loadProgressFromStorage = () => {
      const saved = localStorage.getItem('uploadProgress')
      if (saved) {
        const progressData = JSON.parse(saved)
        addLog(`发现未完成的上传: ${progressData.fileName}`)
        
        // 询问用户是否继续
        if (confirm(`发现未完成的文件 "${progressData.fileName}"，是否继续上传？`)) {
          // 这里可以重新选择文件并恢复上传状态
          initializeChunkStatus()
          progressData.uploadedChunks.forEach(index => {
            if (chunkStatus.value[index]) {
              chunkStatus.value[index].status = 'completed'
            }
          })
          progress.value = (progressData.uploadedChunks.length / chunkStatus.value.length) * 100
        }
      }
    }

    const formatFileSize = (bytes) => {
      if (bytes === 0) return '0 B'
      const k = 1024
      const sizes = ['B', 'KB', 'MB', 'GB']
      const i = Math.floor(Math.log(bytes) / Math.log(k))
      return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
    }

    onMounted(() => {
      loadProgressFromStorage()
    })

    return {
      file,
      uploading,
      paused,
      progress,
      chunkStatus,
      logs,
      handleFileSelect,
      startUpload,
      simulateNetworkError,
      simulateBrowserClose,
      pauseUpload,
      resumeUpload
    }
  }
}
</script>

<style scoped>
.upload-demo {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
}

.controls {
  margin-bottom: 20px;
}

.controls button {
  margin: 5px;
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.controls button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.progress-section {
  margin-bottom: 20px;
}

.progress-bar {
  width: 100%;
  height: 20px;
  background: #f0f0f0;
  border-radius: 10px;
  overflow: hidden;
  margin: 10px 0;
}

.progress-fill {
  height: 100%;
  background: linear-gradient(90deg, #4CAF50, #8BC34A);
  transition: width 0.3s ease;
}

.chunk-status {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-top: 10px;
}

.chunk {
  padding: 4px 8px;
  border-radius: 4px;
  font-size: 12px;
  background: #f5f5f5;
}

.chunk.pending { background: #f5f5f5; color: #999; }
.chunk.uploading { background: #2196F3; color: white; }
.chunk.completed { background: #4CAF50; color: white; }
.chunk.error { background: #f44336; color: white; }

.logs {
  border: 1px solid #ddd;
  border-radius: 8px;
  padding: 15px;
  max-height: 300px;
  overflow-y: auto;
}

.log-item {
  padding: 5px 0;
  border-bottom: 1px solid #f0f0f0;
  font-family: monospace;
  font-size: 12px;
}
</style>